

#pragma once
#include "Vector4.h"
#include "Vector3.h"
#include "Matrix3.h"
#include "Maths.h"

#define EPSILON 0.00001f
#define m_matrix(Row,Col) m_matrix[Row][Col]
class Matrix4 
{
private:
	
public:
	float m_matrix[4][4];
	
	
	Matrix4();
	Matrix4(float*);
	Matrix4( const Matrix4& mt);
	Matrix4( float _11, float _12, float _13, float _14,
			 float _21, float _22, float _23, float _24,
			 float _31, float _32, float _33, float _34,
			 float _41, float _42, float _43, float _44 );

	
	
	float& operator () ( unsigned int Row, unsigned int Col );
	float  operator () ( unsigned int Row, unsigned int Col ) const;

	// assignment operators
	Matrix4 &operator *= (const Matrix4& );
	Matrix4 &operator += (const Matrix4& );
	Matrix4 &operator -= (const Matrix4& );
	Matrix4 &operator *= ( const float );
	Matrix4 &operator /= ( const float );

	Matrix4 operator * ( const float ) const;
	Matrix4 operator / ( const float ) const;
	
	// binary operators
	Matrix4 operator * (const Matrix4& ) const;
	Matrix4 operator + (const Matrix4& ) const;
	Matrix4 operator - (const Matrix4& ) const;
	
	bool operator == (Matrix4& ) const;
	bool operator != (Matrix4& ) const;
	
	// set Value for all element of Matrix
	void setMatrix(float _11, float _12, float _13, float _14,
		float _21, float _22, float _23, float _24,
		float _31, float _32, float _33, float _34,
		float _41, float _42, float _43, float _44 );

	// Translate matrix 4*4 to matrix 3*3
	Matrix3 subMatrix4(const unsigned int i, const unsigned int j) const;
	// Calculating Determinant of matrix 4*4
	float determinant() const ;
	// Get Row of Matrix 4*4
	Vector4 getRow(unsigned int r)const;
	// Get Col of Matrix 4*4
	Vector4 getColumn(unsigned int c)const;
	// Matrix 4*4 Identity
	static void VectorTransformCoord( Vector3& pOut, const Vector3& pV, const Matrix4& pM );
	static void VectorTransformNormal( Vector3& pOut, const Vector3& pV, const Matrix4& pM );
	void setRotateAxis(const float angle, const Vector3& axis);
	void setIdentity();
	void setTranslation(const float sx, const float sy,const float sz);
	void setRotateXAxis(const float xAngle);
	void setRotateYAxis(const float yAngle);
	void setRotateZAxis(const float zAngle);
	//void setRotateAxis( const Vector3& vecAxis, float radians);//(const float Angle,);
	void setMultiply(const Matrix4& a,const Matrix4 &b);
	void setScaling(const float sx, const float sy,const float sz);
	void setInvert();
	bool setPerspectiveFovLH( float FovY, const float Aspect, float nearClip, float farClip );
	bool setLookAtLH(const Vector3& pEye, const Vector3& pAt, const Vector3& pUp);
	friend Matrix4 operator * ( const float f, const Matrix4& );
	static bool Vector3MatrixMultiply(Vector3 &vecDest,const Vector3 &VecSrc,const Matrix4 &mat);
	static Matrix4 Matrix4Identity(Matrix4 & mt);
	static Matrix4 Matrix4Transpose(Matrix4 & mt);
	static Matrix4 Matrix4RotateXAxis(Matrix4 &out_mt,const float xAngle);
	static Matrix4 Matrix4RotateYAxis(Matrix4 &out_mt,const float yAngle);
	static Matrix4 Matrix4RotateZAxis(Matrix4 &out_mt,const float zAngle);
	static Matrix4 Matrix4Translation(Matrix4 & out_mt,const float sx, const float sy,const float sz);
	//static Matrix4 Matrix4Rotate(Matrix4 &mt);
	static Matrix4 Matrix4Scaling(Matrix4 & out_mt,const float sx, const float sy,const float sz);
	
};